package com.gzbd.login.jwt;

import com.gzbd.login.config.AuthConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jdk.nashorn.internal.parser.TokenType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt 工具类
 */
@Component
public class JwtTokenUtil implements Serializable {


    /**
     * token类型
     */
    public static final String TOKEN_TYPE = "tokenType";
    /**
     * 默认token类型
     */
    private static final String TOKEN_DEFAULT_TYPE = TokenType.DEFAULT.toString();
    @Autowired
    private AuthConfig authConfig;

    /**
     * 通过token 获取用户名
     *
     * @param tokenType
     * @param token
     * @return
     */
    public String getUsernameFromToken(String tokenType, String token) {
        Claims claims = getClaimsFromToken(token);
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        if (claims == null || claims.get(TOKEN_TYPE) == null || !tokenType.equals(claims.get(TOKEN_TYPE))) {
            return null;
        }
        return claims.getSubject();
    }


    /**
     * 通过token 获取用户名
     *
     * @param tokenType
     * @param token
     * @return
     */
    public String getDeptIdFromToken(String tokenType, String token) {
        Claims claims = getClaimsFromToken(token);
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        if (claims == null || claims.get(TOKEN_TYPE) == null || !tokenType.equals(claims.get(TOKEN_TYPE))) {
            return null;
        }
        if (claims.get("deptId") == null) {
            return null;
        }
        return claims.get("deptId").toString();
    }

    public String getRoleIdFromToken(String tokenType, String token) {
        Claims claims = getClaimsFromToken(token);
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        if (claims == null || claims.get(TOKEN_TYPE) == null || !tokenType.equals(claims.get(TOKEN_TYPE))) {
            return null;
        }
        if (claims.get("roleId") == null) {
            return null;
        }
        return claims.get("roleId").toString();
    }

    /**
     * 通过token 获取创建时间
     *
     * @param tokenType
     * @param token
     * @return
     */
    public Date getCreatedDateFromToken(String tokenType, String token) {
        Claims claims = getClaimsFromToken(token);
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        if (claims == null || claims.get(TOKEN_TYPE) == null || !claims.get(TOKEN_TYPE).toString().equals(tokenType)) {
            return null;
        }
        return claims.getIssuedAt();
    }

    /**
     * 通过token 获取过期时间
     *
     * @param tokenType
     * @param token
     * @return
     */
    public Date getExpirationDateFromToken(String tokenType, String token) {
        Claims claims = getClaimsFromToken(token);
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        if (claims == null || claims.get(TOKEN_TYPE) == null || !claims.get(TOKEN_TYPE).toString().equals(tokenType)) {
            return null;
        }
        return claims.getExpiration();
    }

    /**
     * 通过token 获取数据声明
     *
     * @param token
     * @return
     */
    public Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(authConfig.getSecret())
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    /**
     * 生成token 过期时间
     *
     * @return
     */
    private Date generateExpirationDate() {
        long expirationTime = System.currentTimeMillis() + authConfig.getExpiration() * 1000;
        return new Date(expirationTime);
    }

    /**
     * 生成token 过期时间
     *
     * @return
     */
    private Date generateExpirationDateFor3() {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_YEAR,3);
        return calendar.getTime();
    }

    /**
     * token是否过期
     *
     * @param tokenType
     * @param token
     * @return
     */
    public Boolean isTokenExpired(String tokenType, String token) {
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        Date expiration = getExpirationDateFromToken(tokenType, token);
        return expiration == null || expiration.before(new Date());
    }



    /**
     * 生成token
     *
     * @param tokenType
     * @return
     */
    public String generateToken(String tokenType, String username, String deptId, String roleId) {
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        Map<String, Object> claims = new HashMap<>();
        //token类型
        claims.put(TOKEN_TYPE, tokenType);
        //用户名
        claims.put(Claims.SUBJECT, username);
        //部门ID
        claims.put("deptId", deptId);
        claims.put("roleId", roleId);
        return generateToken(claims);
    }

    /**
     * 生成永久token
     *
     * @param tokenType
     * @return
     */
    public String generateTokenForever(String tokenType, String username, String deptId, String roleId) {
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        Map<String, Object> claims = new HashMap<>();
        //token类型
        claims.put(TOKEN_TYPE, tokenType);
        //用户名
        claims.put(Claims.SUBJECT, username);
        //部门ID
        claims.put("deptId", deptId);
        claims.put("roleId", roleId);

        return generateTokenExpiration(claims);
    }

    /**
     * 生成永久token
     *
     * @param claims
     * @return
     */
    private String generateTokenExpiration(Map<String, Object> claims) {
        String token;
        try {
            token = Jwts.builder()
                    .setClaims(claims)
                    //创建时间
                    .setIssuedAt(new Date())
                    //过期时间
                    .setExpiration(generateExpirationDateFor3())
                    //算法
                    .signWith(SignatureAlgorithm.HS512, authConfig.getSecret())
                    .compact();
        } catch (Exception e) {
            token = null;
        }
        return token;
    }


    /**
     * 生成token
     *
     * @param claims
     * @return
     */
    private String generateToken(Map<String, Object> claims) {
        String token;
        try {
            token = Jwts.builder()
                    .setClaims(claims)
                    //创建时间
                    .setIssuedAt(new Date())
                    //过期时间
                    .setExpiration(generateExpirationDate())
                    //算法
                    .signWith(SignatureAlgorithm.HS512, authConfig.getSecret())
                    .compact();
        } catch (Exception e) {
            token = null;
        }
        return token;
    }


    /**
     * 校验token是否有效
     *
     * @param tokenType    用户类型
     * @param token        token
     * @param authUsername 登录用户
     * @return Boolean
     */
    public Boolean validateToken(String tokenType, String token, String authUsername) {
        if (tokenType == null) {
            tokenType = TOKEN_DEFAULT_TYPE;
        }
        String username = getUsernameFromToken(tokenType, token);
        Date createdDate = getCreatedDateFromToken(tokenType, token);
        return username != null && createdDate != null
                && username.equals(authUsername) //用户名是否相同
                && !isTokenExpired(tokenType, token);//token是否过期
//                && !isPasswordReset(createdDate, timeOut);//在创建token之后重置过密码
    }


}

